package controllers;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import javax.imageio.ImageIO;
import javax.persistence.Query;

import org.apache.ivy.plugins.matcher.NoMatcher;

import com.thoughtworks.xstream.converters.extended.GregorianCalendarConverter;

import models.Avaliacao;
import models.Emprestimo;
import models.Notificacao;
import models.StatusEmprestimo;
import models.TipoAvaliacao;
import models.TipoNotificacao;
import models.livro.Livro;
import models.livro.LivroLocatario;
import models.livro.LivroUsuario;
import models.livro.StatusLivro;
import models.usuario.Perfil;
import models.usuario.Usuario;
import play.Play;
import play.cache.Cache;
import play.data.binding.As;
import play.data.validation.Email;
import play.data.validation.Required;
import play.db.jpa.Blob;
import play.db.jpa.JPA;
import play.libs.MimeTypes;
import play.mvc.*;
import sun.awt.image.FileImageSource;
import sun.util.calendar.Gregorian;
@With(Seguranca.class)
public class Panel extends Controller {

    @Before
    static void setUsuarioConectado(){
    	  if(Security.isConnected()) {
              Usuario user = Usuario.find("byEmail", Security.connected()).first();
              renderArgs.put("usuario", user.email);
          }
    }
	
	public static void index() {
		String usuarioConectado = Security.connected();
		Usuario usuario = Usuario.find("byEmail", usuarioConectado).first();
		List<Notificacao> usuarioNotificacoes = usuario.notificacoes;
		List<String> notificacoes= new ArrayList<String>();
		if(usuarioNotificacoes.size()>5){
			for(int i = usuarioNotificacoes.size()-1;i>=1;i--){
				notificacoes.add(usuarioNotificacoes.get(i).toString());
			}
			  render(notificacoes);
		}

		for (int i = usuarioNotificacoes.size()-1;i>=0;i--) {
			notificacoes.add(usuarioNotificacoes.get(i).toString());
		}
        render(notificacoes);
    }
    
    public static void cadastrarLivro() {
        render();
    }
    
    public static void exibirEstante(){
    	render();
    }
    
    public static void exibirMeuPerfil(){
    	String usuario = Security.connected();
    	Usuario usuarioConectado = Usuario.find("byEmail", usuario).first();
    	render(usuarioConectado);
    }
    
    public static void edicaoPerfil(){
    	String usuario = Security.connected();
    	Usuario usuarioConectado = Usuario.find("byEmail", usuario).first();
    	render(usuarioConectado);
    }
    public static void alterarFoto(){
    	render();
    }
    
    public static void alterarSenha(){
    	render();
    }
    public static void listarNotificacoes(){
    	String usuarioConectado = Security.connected();
		Usuario usuario = Usuario.find("byEmail", usuarioConectado).first();
		List<Notificacao> usuarioNotificacoes = usuario.notificacoes;
		List<String> notificacoes= new ArrayList<String>();
		for(int i = usuarioNotificacoes.size()-1;i>=0;i--){
			notificacoes.add(usuarioNotificacoes.get(i).toString());
		}
        render(notificacoes);
    }
    
    public static void limparAreaNotificacao(){
    	String usuarioConectado = Security.connected();
		Usuario usuario = Usuario.find("byEmail", usuarioConectado).first();
		List<Notificacao> usuarioNotificacoes = usuario.notificacoes;
		for (Notificacao notificacao : usuarioNotificacoes) {
			notificacao.delete();
		}
		usuario.save();
		index();
    }
    
    public static void limparNotificacoes(){
    	String usuarioConectado = Security.connected();
		Usuario usuario = Usuario.find("byEmail", usuarioConectado).first();
		List<Notificacao> usuarioNotificacoes = usuario.notificacoes;
		for (Notificacao notificacao : usuarioNotificacoes) {
			notificacao.delete();
		}
		usuario.save();
		index();
    }
    
    public static void avaliarEmprestimoLocatario(@Required String nomeLivro, @Required @Email String emailProprietario){
    	flash.put("nomeLivro", nomeLivro);
    	flash.put("emailProprietario", emailProprietario);
    	render();
    }
    
    
    public static void avaliarEmprestimoProprietario(@Required String nomeLivro, @Required @Email String emailLocatario){
    	flash.put("nomeLivro", nomeLivro);
    	flash.put("emailLocatario", emailLocatario);
    	render();
    }
    
    //página de pedido de empréstimo
    public static void pedirEmprestado(@Required String nomeLivro){
    	try{
    	flash.put("nomeLivro", nomeLivro);
    	String usuarioConectado = Security.connected();
    	List<Usuario> proprietarios = new ArrayList<Usuario>();
    	List<LivroUsuario> livros = LivroUsuario.findAll();
    	for (LivroUsuario l : livros) {
			if(l.livro.nome.equals(nomeLivro)){
				if(!l.proprietario.email.equals(usuarioConectado))
				proprietarios.add(l.proprietario);
			}
		}
    	render(proprietarios);
    	}
    	catch (Exception e) {
			error(e);
		}
    }
    
    public static void emprestar() {
    	String user = Security.connected();
    	List<LivroUsuario> livros = LivroUsuario.find("proprietario.email like ? order by livro.nome", user).fetch();
    	List<Usuario> usuarios = Usuario.find("email not like ? order by email", user).fetch();
        render(livros, usuarios);
    }
    
    public static void listarLivros() {
    	List<Livro> livros = Livro.find("order by nome").fetch();
    	render(livros);
    }
    
    public static void listarUsuarios() {
    	List<Usuario> usuarios = Usuario.find("order by email").fetch();
    	render(usuarios);
    }
    
    //lista os livros do usuário conectado
    public static void listarLivrosDoUsuario(){
    	String user = Security.connected();
    	List<LivroUsuario> livros = LivroUsuario.find("proprietario.email like ? order by livro.nome", user).fetch();
    	List<Usuario> usuarios = Usuario.find("email not like ? order by email", user).fetch();
    	render(livros,usuarios);
    }
    
    public static void listarEmprestimos() {
    	List<Emprestimo> emprestimos = Emprestimo.find("order by livroEmprestado").fetch();
    	render(emprestimos);
    }
    
    //realiza uma pesquisa de usuarios
    public static void realizarPesquisaUsuario(String texto){
    	List<Usuario> usuarios = Usuario.find("email like ? order by email", "%"+texto+"%").fetch();
    	render(usuarios);
    }
    
    //realiza uma pesquisa de livros
    public static void realizarPesquisaLivro(String texto){
    	List<Livro> livros = Livro.find("nome like ? order by nome", "%"+texto+"%").fetch();
    	render(livros);
    }
    
    public static void realizarPesquisaLivroCentral(String textoLivro){
    	List<Livro> livros = Livro.find("nome like ? order by nome", "%"+textoLivro+"%").fetch();
    	render(livros);
    }
    public static void pesquisaLivroIsbn(String textoLivro){
    	List<Livro> livros = Livro.find("ISBN like ? order by ISBN", "%"+textoLivro+"%").fetch();
    	render(livros);
    }
    
    public static void pesquisaAutor(String textoLivro){
    	List<Livro> livros = Livro.find("autor like ? order by autor", "%"+textoLivro+"%").fetch();
    	render(livros);
    }
    
    //Exibe detalhes de um livro
    public static void detalhesLivro(@Required String livroNome){
    	try{
    	Livro livro = Livro.find("byNome", livroNome).first();
    	List<Usuario> proprietarios = new ArrayList<Usuario>();
    	List<LivroUsuario> livros = LivroUsuario.findAll();
    	for (LivroUsuario l : livros) {
			if(l.livro.nome.equalsIgnoreCase(livroNome)){
				proprietarios.add(l.proprietario);
			}
		}

    	render(livro,proprietarios);
    	}
    	catch (Exception e) {
    		notFound();
		}
    }
    
    //Exibe detalhes de um livro na estante do usuário conectado
    public static void detalhesLivroEstante(@Required String livroNome){
    	String user = Security.connected();
    	LivroUsuario livro = LivroUsuario.find("byProprietario.emailAndLivro.nome",user,livroNome).first();
    	render(livro);
    	
    
    }
    /**
     * Adiciona um livro cadastrado a lista de livros do usuário.
     * @param nomeLivro Nome do livro cadastrado a ser adicionado
     * na estante do usuario.
     * @param emailProprietario Email do usuário que está adicionando
     * um livro a sua estante.
     */
    public static void adicionarLivroEstante(@Required String nomeLivro, @Required @Email String emailProprietario){
    	flash.put("url", "/panel/detalheslivro?livroNome="+nomeLivro);
    	Usuario proprietario = Usuario.find("byEmail", emailProprietario).first();
    	Livro livro = Livro.find("byNome", nomeLivro).first();
    	
    	LivroUsuario livroChecagem = LivroUsuario.find("byProprietario.emailAndLivro.nome",emailProprietario,livro.nome).first();
    	//Impede que o usuário adicione um livro que já está na sua estante
    	if(livroChecagem!=null){
    		flash.keep("url");
			flash.error("estante.error");
			params.flash();
			detalhesLivro(nomeLivro);
    	}
    	
    	LivroUsuario livroUsuario = new LivroUsuario(livro, proprietario);
    	livroUsuario.status = StatusLivro.DISPONIVEL;
    	livroUsuario.save();
    	livroUsuario.proprietario.livros.add(livroUsuario);
    	redirect("/panel/listarlivrosdousuario");
    }
    
    /**
     * Remove um livro da lista de livros do usuário.
     * @param nomeLivro Nome do livro cadastrado a ser adicionado
     * na estante do usuario.
     * @param emailProprietario Email do usuário que está adicionando
     * um livro a sua estante.
     */
    public static void removerLivroEstante(@Required String nomeLivro, @Required @Email String emailProprietario){
    	try{
    	flash.put("url", "/panel/detalheslivroestante?livroNome="+nomeLivro);
    	LivroUsuario livroChecagem = LivroUsuario.find("byProprietario.emailAndLivro.nome",emailProprietario,nomeLivro).first();
    	
    	if(livroChecagem.status==StatusLivro.EMPRESTADO){
    		flash.keep("url");
			flash.error("removerEstante.error");
			params.flash();
			detalhesLivroEstante(nomeLivro);
    	}
    	
    	livroChecagem.delete();
    	redirect("/panel/listarlivrosdousuario");
    	}
    	catch (Exception e) {
			error(e);
		}
    }
    
    /**
     * Adiciona um livro ao sistema.
     * @param nome Nome do livro a ser adicionado ao sistema.
     * @throws FileNotFoundException 
     */
    public static void adicionarLivro(@Required String nome,String isbn,@Required String autor,String descricao,File capa) throws FileNotFoundException{
    	flash.put("url", "panel/cadastrarlivro");
    	//verfica se o livro já existe
    	Livro l = Livro.find("byNomeLike", nome).first();
    	if(l!=null){
    	  	flash.keep("url");
        	flash.error("registrarlivro.errorExistente");
        	params.flash();
        	cadastrarLivro();
    	}
    	
    	if(validation.hasErrors()){
    		flash.keep("url");
    		flash.error("registrar.errorCampos");
    		params.flash();
    		cadastrarLivro();
    	}
    	
    	
    	Livro livro = new Livro(nome,isbn,autor,descricao);
    	livro.save();
    	if(capa==null){
    		livro.capa=null;
    		livro.save();
        	flash.keep("url");
        	flash.success("cadastrarlivro.success");
        	params.flash();
        	cadastrarLivro();		
    	}
     	livro.capa = new Blob();
    	livro.capa.set(new FileInputStream(capa), MimeTypes.getContentType(capa.getName()));
    	livro.save();
    	flash.keep("url");
    	flash.success("cadastrarlivro.success");
    	params.flash();
    	cadastrarLivro();
    }
    
    /**
     * Cria um notificação na área de inicial de todos os usários que possuem o livro solicitado sobre
     * o pedido de empréstimo de um  usuário
     * **/
	@SuppressWarnings("deprecation")
	public static void pedirEmprestadoTodos(@Required String nomeLivro){
    	flash.put("url", "/panel/detalheslivro?livroNome="+nomeLivro);
    	Date dataAtual = new Date();
    	String usuarioConectado = Security.connected();
    	Usuario usuario = Usuario.find("byEmail", usuarioConectado).first();
    	List<LivroUsuario> livrosUsuario = LivroUsuario.find("proprietario.email like ?",usuarioConectado).fetch();
    	//Impede que o usuário faça um pedido de um livro que já possui
    	for (LivroUsuario l : livrosUsuario) {
			if(l.livro.nome.equalsIgnoreCase(nomeLivro)){
				flash.keep("url");
				flash.error("estante.error");
				params.flash();
				detalhesLivro(nomeLivro);
			}
		}
    	
    	//checagem livro emprestado
    	LivroLocatario checagemLivro = LivroLocatario.find("byLivro.nomeAndLocatario", nomeLivro,usuario).first();
    	if(checagemLivro!=null){
    		flash.keep("url");
			flash.error("pedido.jaEmprestou");
			params.flash();
			detalhesLivro(nomeLivro);
    	}
    	
    	//checagem notificações recentes
    	Notificacao checagemNotificacao = Notificacao.find("byRemetenteAndNomeLivroAndTipoNotificacao", usuario,nomeLivro,TipoNotificacao.PEDIDO_EMPRESTIMO).first();
    	if(checagemNotificacao!=null){
    		int dif = dataAtual.getHours()-checagemNotificacao.dataNotificacao.getHours();
    		if(dif<12){
    			flash.keep("url");
    			flash.error("pedidoRecente.error");
    			params.flash();
    			detalhesLivro(nomeLivro);
    		}
    	}
    	
    	//lista os livros disponíveis e adiciona uma notificação em cada proprietário
    	List<LivroUsuario> livrosDisponiveis = LivroUsuario.find("byLivro.nomeAndStatus", nomeLivro,StatusLivro.DISPONIVEL).fetch();
    	if(livrosDisponiveis.isEmpty()){
    		flash.keep("url");
			flash.error("pedirTodos.error");
			params.flash();
			detalhesLivro(nomeLivro);
    	}
    	for (LivroUsuario livroUsuario : livrosDisponiveis) {
    		Notificacao notificacao = new Notificacao(usuario, livroUsuario.proprietario, nomeLivro,TipoNotificacao.PEDIDO_EMPRESTIMO).save();
			livroUsuario.proprietario.notificacoes.add(notificacao);
			livroUsuario.proprietario.save();
		}
    	flash.keep("url");
    	flash.success("pedirLivro.success");
    	params.flash();
    	detalhesLivro(nomeLivro);
    	
    }
    
    /**
     * Cria um notificação na área de inicial de um usário em particular que possui o livro solicitado sobre
     * o pedido de empréstimo de um  usuário
     * **/
    @SuppressWarnings("deprecation")
	public static void pedirEmprestadoProprietario(@Required @Email String emailProprietario){
    	String nomeLivro = flash.get("nomeLivro");
    	flash.put("url","/panel/pediremprestado?nomeLivro="+nomeLivro);
    	Date dataAtual = new Date();
    	String usuarioConectado = Security.connected();
    	Usuario usuario = Usuario.find("byEmail", usuarioConectado).first();
    	List<LivroUsuario> livrosUsuario = LivroUsuario.find("proprietario.email",usuarioConectado).fetch();
    	//Impede que o usuário faça um pedido de um livro que já possui
    	for (LivroUsuario l : livrosUsuario) {
			if(l.livro.nome.equalsIgnoreCase(nomeLivro)){
				flash.keep("url");
				flash.error("estante.error");
				params.flash();
				pedirEmprestado(nomeLivro);
			}

		}
    	
    	LivroUsuario livroUsuario  = LivroUsuario.find("byLivro.nomeAndProprietario.email",
    			nomeLivro,emailProprietario).first();
    	if(livroUsuario==null){
    		notFound();
    	}
    	
    	if(livroUsuario.status.equals(StatusLivro.EMPRESTADO)){
    		flash.keep("url");
			flash.error("pedirLivro.error");
			params.flash();
			pedirEmprestado(nomeLivro);
    	}
    	//checagem livro emprestado
    	LivroLocatario checagemLivro = LivroLocatario.find("byLivro.nomeAndLocatario", nomeLivro,usuario).first();
    	if(checagemLivro!=null){
    		flash.keep("url");
			flash.error("pedido.jaEmprestou");
			params.flash();
			pedirEmprestado(nomeLivro);
    	}
    	
    	//checagem notificações recentes
    	Notificacao checagemNotificacao = Notificacao.find("byRemetenteAndNomeLivroAndDestinatario.emailAndTipoNotificacao", usuario,nomeLivro,emailProprietario,TipoNotificacao.PEDIDO_EMPRESTIMO).first();
    	if(checagemNotificacao!=null){
    		int dif = dataAtual.getHours()-checagemNotificacao.dataNotificacao.getHours();
    		if(dif<12){
    			flash.keep("url");
    			flash.error("pedidoRecente.error");
    			params.flash();
    			pedirEmprestado(nomeLivro);
    		}
    	}
		Notificacao notificacao = new Notificacao(usuario, livroUsuario.proprietario, nomeLivro,TipoNotificacao.PEDIDO_EMPRESTIMO).save();
		livroUsuario.proprietario.notificacoes.add(notificacao);
		livroUsuario.proprietario.save();
		
		flash.keep("url");
    	flash.success("pedirLivro.success");
    	params.flash();
    	pedirEmprestado(nomeLivro);
 	
    }
    /**Exibe os livros emprestados pelo usuário conectado
     * **/
    public static void exibirLivrosEmprestadosPorUsuario(){
    	String user = Security.connected();
    	List<LivroLocatario> livros = LivroLocatario.find("locatario.email like ? order by livro.nome", user).fetch();
    	render(livros);
    }
    
    /**Exibe os livros do usuário que estão emprestados por outros usuários
     * **/
    public static void exibirLivrosEmprestadosDeUsuario(){
    	String user = Security.connected();
    	List<LivroLocatario> livros = LivroLocatario.find("proprietario.email like ? order by livro.nome", user).fetch();
    	render(livros);
    }
    
    public static void detalhesLivroEmprestadoPorUsuario(@Required String nomeLivro){
    	String user = Security.connected();
	    	LivroLocatario livro = LivroLocatario.find("byLocatario.emailAndLivro.nomeLike",user,nomeLivro).first();
	    	Usuario proprietarioOriginal = Usuario.find("byEmail", livro.proprietario.email).first();
	    	render(livro,proprietarioOriginal);
    	
    	
    }
    
    public static void detalhesLivroEmprestadoDeUsuario(@Required String nomeLivro){
    	String user = Security.connected();
    	
	    	LivroLocatario livro = LivroLocatario.find("byProprietario.emailAndLivro.nomeLike",user,nomeLivro).first();
	    	Usuario locatario = Usuario.find("byEmail", livro.locatario.email).first();
	    	render(livro,locatario);
    
    }
    
    
    /**
     * Avalicação feita pelo locatário do livro no momento da devolução do livro
     * **/
    public static void registrarAvaliacaoLocatario(@Required String tipoAvaliacao, String descricao){
    	String nomeLivro = flash.get("nomeLivro");
    	String emailProprietario = flash.get("emailProprietario");
    	Usuario proprietario = Usuario.find("byEmail", emailProprietario).first();
    	flash.put("url", "/panel/avaliaremprestimolocatario?nomeLivro="+nomeLivro+"&emailProprietario="+emailProprietario);
    	if(validation.hasErrors()){
    		flash.keep("url");
    		flash.error("devolver.errorCampos");
    		params.flash();
    		avaliarEmprestimoLocatario(nomeLivro,emailProprietario);
    	}
    	
 		String usuarioConectado = Security.connected();
		Usuario locatario = Usuario.find("byEmail", usuarioConectado).first();
		LivroUsuario livroUsuario = LivroUsuario.find("byLivro.nomeAndProprietario.email", nomeLivro,emailProprietario).first();
		LivroLocatario livroLocatario = LivroLocatario.find("byLivro.nomeAndProprietario.emailAndLocatario", nomeLivro,
				emailProprietario,locatario).first();
		if(livroLocatario==null){
			flash.keep("url");
    		flash.error("devolver.errorLivroNaoEncontrado");
    		params.flash();
    		avaliarEmprestimoLocatario(nomeLivro,emailProprietario);
		}
		
		Emprestimo checagem = Emprestimo.find("byLivroEmprestadoAndLocatarioAndStatus",
				livroUsuario,locatario,StatusEmprestimo.INICIO_FINALIZACAO).first();
		if(checagem!=null){
			flash.keep("url");
    		flash.error("devolver.devolucaoIniciada");
    		params.flash();
    		avaliarEmprestimoLocatario(nomeLivro,emailProprietario);
		}
    		
    	TipoAvaliacao tipo = null;
    	if(tipoAvaliacao.equalsIgnoreCase("Bom"))
    		tipo = TipoAvaliacao.BOM;
    	else if(tipoAvaliacao.equalsIgnoreCase("Regular"))
    		tipo = TipoAvaliacao.REGULAR;
    	else if(tipoAvaliacao.equalsIgnoreCase("Ruim"))
    		tipo = TipoAvaliacao.RUIM;
    	
    	//Cria a avalicação
    	Avaliacao avaliacaoLocatario = new Avaliacao(tipo, descricao);
    	avaliacaoLocatario.save();
    	
    	Emprestimo emprestimo = Emprestimo.find("byLivroEmprestadoAndLocatarioAndStatus",
    			livroUsuario,locatario,StatusEmprestimo.INICIADO).first();
    	
		emprestimo.setAvaliacaoLocatario(avaliacaoLocatario);
		emprestimo.setStatus(StatusEmprestimo.INICIO_FINALIZACAO);
		emprestimo.save();
		
		//Adiciona a notificação de início de devolução no proprietário.
		Notificacao notificacao = new Notificacao(locatario, proprietario, nomeLivro, TipoNotificacao.INICIO_DEVOLUCAO).save();
		proprietario.notificacoes.add(notificacao);
		proprietario.save();

    	flash.keep("url");
    	flash.success("inicioDevolucao.success");
    	params.flash();
    	avaliarEmprestimoLocatario(nomeLivro, emailProprietario);
    }
    
    /**
     * Avaliação do proprietário do livro no momento da confirmação da devolução
     * **/
    public static void registrarAvaliacaoProprietario(@Required String tipoAvaliacao, String descricao){  	
    	String nomeLivro = flash.get("nomeLivro");
    	String emailLocatario = flash.get("emailLocatario");
    	flash.put("url", "/panel/avaliaremprestimoproprietario?nomeLivro="+nomeLivro+"&emailLocatario="+emailLocatario);
    	String usuarioConectado = Security.connected();
    	Usuario proprietario = Usuario.find("byEmail", usuarioConectado).first();
		Usuario locatario = Usuario.find("byEmail", emailLocatario).first();
		LivroUsuario livroUsuario = LivroUsuario.find("byLivro.nomeAndProprietario.email", nomeLivro,usuarioConectado).first();
		LivroLocatario livroLocatario = LivroLocatario.find("byLivro.nomeAndProprietario.emailAndLocatario", nomeLivro,
				usuarioConectado,locatario).first();
		if(livroLocatario==null){
			flash.keep("url");
    		flash.error("devolver.errorLivroNaoEncontrado");
    		params.flash();
    		avaliarEmprestimoProprietario(nomeLivro,emailLocatario);
		}
	

    	if(validation.hasErrors()){
    		flash.keep("url");
    		flash.error("devolver.errorCampos");
    		params.flash();
    		avaliarEmprestimoProprietario(nomeLivro,emailLocatario);
    	}
    	
    	
    	TipoAvaliacao tipo = null;
    	if(tipoAvaliacao.equalsIgnoreCase("Bom"))
    		tipo = TipoAvaliacao.BOM;
    	else if(tipoAvaliacao.equalsIgnoreCase("Regular"))
    		tipo = TipoAvaliacao.REGULAR;
    	else if(tipoAvaliacao.equalsIgnoreCase("Ruim"))
    		tipo = TipoAvaliacao.RUIM;
    	
    	Emprestimo checagem = Emprestimo.find("byLivroEmprestadoAndLocatarioAndStatus",
				livroUsuario,locatario,StatusEmprestimo.INICIO_FINALIZACAO).first();
    	if(checagem==null){
    		flash.keep("url");
    		flash.error("devolver.devolucaoNaoIniciada");
    		params.flash();
    		avaliarEmprestimoProprietario(nomeLivro,emailLocatario);
    	}
    	
    	//Cria a avalicação
    	Avaliacao avaliacaoProprietario = new Avaliacao(tipo, descricao);
    	avaliacaoProprietario.save();
    	
    	//Devolve livro ao proprietário
		livroUsuario.setStatus(StatusLivro.DISPONIVEL);
				
		
		checagem.setStatus(StatusEmprestimo.FINALIZADO);
		checagem.setAvaliacaoLocatario(avaliacaoProprietario);
		
		Notificacao notificacao = new Notificacao(proprietario, locatario, nomeLivro, TipoNotificacao.CONFIRMACAO_DEVOLUCAO).save();
		locatario.notificacoes.add(notificacao);
		livroLocatario.delete();
		livroUsuario.save();
		checagem.save();
		locatario.save();
		proprietario.save();
		
    	flash.keep("url");
    	flash.success("devolver.success");
    	params.flash();
    	avaliarEmprestimoProprietario(nomeLivro, emailLocatario);
    }
    /**
     * Empresta um livro entre os usuários.
     * @param nomeLivro Nome do livro a ser emprestado.
     * @param emailProprietario Email do usuário que detém o livro a ser emprestado.
     * @param emailLocatario Email do usuário que deseja pegar o livro a ser emprestado.
     */
    public static void emprestarLivro(@Required String nomeLivro, @Required @Email String emailLocatario){
    	flash.put("url", "panel/listarlivrosdousuario");
    	String usuarioConectado = Security.connected();
    	Usuario usuario = Usuario.find("byEmail",usuarioConectado).first();
    	if(validation.hasErrors()){
    		flash.keep("url");
    		flash.error("emprestar.errorCampos");
    		params.flash();
    		listarLivrosDoUsuario();
    	}
    	
    	LivroUsuario livroLocatario = LivroUsuario.find("byLivro.nomeAndProprietario.email", nomeLivro,emailLocatario).first();
    	if(livroLocatario!=null){
    		flash.keep("url");
    		flash.error("emprestarError.locatarioJaPossui");
    		params.flash();
    		listarLivrosDoUsuario();
    	}
    	
    	Usuario locatario = Usuario.find("byEmail", emailLocatario).first();
    	
    	LivroUsuario livroUsuario = null;
    	
    	
    	for(LivroUsuario l : LivroUsuario.<LivroUsuario>findAll()) {
    	    if(l.livro.nome.equalsIgnoreCase(nomeLivro)) {
    	    	if(l.status.equals(StatusLivro.EMPRESTADO)){
    	    		flash.keep("url");
	        		flash.error("emprestar.errorJaEmprestado");
	        		params.flash();
	        		listarLivrosDoUsuario();
    	    	}
    	    	l.setStatus(StatusLivro.EMPRESTADO);
    	    	l.save();
    	    	livroUsuario = l;
    			break;
    		}
    	}
    	Emprestimo emprestimo = new Emprestimo(livroUsuario, locatario);
    	emprestimo.setStatus(StatusEmprestimo.INICIADO);
    	LivroLocatario livro = new LivroLocatario(livroUsuario.livro, livroUsuario.proprietario, locatario);
    	locatario.livrosEmprestados.add(livro);
    	
    	Notificacao notificacao = new Notificacao(usuario, locatario, nomeLivro, TipoNotificacao.REALIZACAO_EMPRESTIMO).save();
    	locatario.notificacoes.add(notificacao);
    	livro.save();
		emprestimo.save();
		locatario.save();
		
    		
    	flash.keep("url");
    	flash.success("emprestar.success");
    	params.flash();
    	listarLivrosDoUsuario();
    }
    
    
    /**
     * Renderiza uma capa de livro forncecendo o nome de um livro
     * **/
    public static void getCapa(String livroNome) {
    	 Livro livro = Livro.find("byNome", livroNome).first();
         if(livro.capa.get()==null){
         	File f= Play.getFile("/public/images/sem-imagem.jpg");
         	renderBinary(f);
         }
         response.setContentTypeIfNotSet(livro.capa.type());
         renderBinary(livro.capa.get());
    }
    
    /**
     * Renderiza uma foto de perfil do usuário
     * **/
    public static void getFotoPerfil(String emailUsuario){
    	Usuario usuario = Usuario.find("byEmail", emailUsuario).first();
    	 if(usuario.perfil.fotoPerfil.get()==null){
          	File f= Play.getFile("/public/images/sem-imagem-perfil.jpg");
          	renderBinary(f);
          }
    	 response.setContentTypeIfNotSet(usuario.perfil.fotoPerfil.type());
         renderBinary(usuario.perfil.fotoPerfil.get());
    }
    
    /**
     * Altera a foto do perfil do usuario
     * @throws FileNotFoundException 
     * **/
    public static void alterarFotoPerfil(@Required File foto) throws FileNotFoundException{
    	flash.put("url", "panel/alterarfoto");
    	if(validation.hasErrors()){
    		flash.keep("url");
    		flash.error("foto.errorCampos");
    		params.flash();
    		alterarFoto();
    	}
    	String usuarioConectado = Security.connected();
    	Usuario usuario = Usuario.find("byEmail",usuarioConectado).first();
    	if(usuario.perfil.fotoPerfil.get()!=null){
    		usuario.perfil.fotoPerfil.getFile().delete();
    	}
    	usuario.perfil.fotoPerfil = new Blob();
    	usuario.perfil.fotoPerfil.set(new FileInputStream(foto), MimeTypes.getContentType(foto.getName()));
    	usuario.perfil.save();
    	usuario.save();
    	exibirMeuPerfil();
    }
    
    public static void removerFotoPerfil(){
    	try{
    		String usuarioConectado = Security.connected();
        	Usuario usuario = Usuario.find("byEmail",usuarioConectado).first();
        	usuario.perfil.fotoPerfil.getFile().delete();
        	usuario.perfil.fotoPerfil = null;
        	usuario.perfil.save();
        	usuario.save();
        	exibirMeuPerfil();
    	}
    	catch (Exception e) {
			error(e);
		}
    }
    
    public static void editarPerfil(@Required String nomeCompleto,Date dataNascimento,
    		String telefone,String celular){
    	flash.put("url", "panel/edicaoperfil");
    	String usuarioConectado = Security.connected();
    	Usuario usuario = Usuario.find("byEmail",usuarioConectado).first();
    	if(validation.hasErrors()){
    		flash.keep("url");
    		flash.error("registrar.errorCampos");
    		params.flash();
    		edicaoPerfil();
    	}
    	usuario.perfil.nome = nomeCompleto;
    	usuario.perfil.dataNascimento = dataNascimento;
    	usuario.perfil.telefone = telefone;
    	usuario.perfil.celular = celular;
    	usuario.save();
    	
    	flash.keep("url");
		flash.error("editarPerfil.success");
		params.flash();
		edicaoPerfil();
    }
    
    /**
     * Altera a senha de um usuário
     * **/
    public static void alterarSenha(@Required String senhaAtual, @Required String senhaNova){
    	
    }
    
   /**
    * Exibe o perfil de um usuário  
    * @param emailUsuario do usuario.
    * **/
    public static void exibirPerfilUsuario(@Required String emailUsuario){
    	Usuario user = Usuario.find("byEmail", emailUsuario).first();
    	render(user);
    }
}
